package com.cc.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cc.base.PageResponse;
import com.cc.base.ResponseResult;
import com.cc.enums.HttpsCode;
import com.cc.enums.UserEnmu;
import com.cc.exception.BusinessException;
import com.cc.mapper.UserMapper;
import com.cc.pojo.domain.Role;
import com.cc.pojo.domain.User;
import com.cc.pojo.dto.LoginDto;
import com.cc.pojo.dto.RegisterDto;
import com.cc.pojo.dto.UserDto;
import com.cc.pojo.dto.UserPageDto;
import com.cc.pojo.vo.UserVo;
import com.cc.service.UserService;
import com.cc.utils.IpUtils;
import com.cc.utils.PasswordUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Resource
    private UserMapper userMapper;

    /**
     * 登录
     *
     * @param loginDto
     * @return
     */
    @Override
    public ResponseResult<Map> login(LoginDto loginDto, HttpServletRequest request) {
        //1.检查参数
        if (loginDto.getUsername() == null || loginDto.getPassword() == null) {
            throw new BusinessException(HttpsCode.PARAMS_ERROR, "账号或密码为空");
        }
        //获取登录用户
        User user = getOne(Wrappers.<User>lambdaQuery().eq(User::getUserName, loginDto.getUsername()));
        if (user == null) {
            throw new BusinessException(HttpsCode.ACCOUNT_NOT_EXIST);
        }
        //检查用户是否被封禁
        if (UserEnmu.USER_STATUS_BLOCKED.equals(user.getStatus()) || StpUtil.isDisable(user.getUserId())) {
            throw new BusinessException(HttpsCode.ACCOUNT_BLOCKED);
        }
        String password = user.getPassword();
        String loginDtoPassword = loginDto.getPassword();
        if (!password.equals(PasswordUtils.encrypt(loginDtoPassword))) {
            throw new BusinessException(HttpsCode.ACCOUNT_OR_PASSWORD_ERROR);
        }
        StpUtil.login(user.getUserId());
        //将用户登录的ip信息进行存储
        String ipAddress = IpUtils.getIpAddress(request);
        if (StrUtil.isNotBlank(ipAddress)) {
            //ip转换成地址
            String ipAttribution = IpUtils.changeIpToAddress(ipAddress);
            user.setLoginIp(ipAddress);
            user.setLoginIpAttribution(ipAttribution);
            user.setLoginDate(LocalDateTime.now());
            updateById(user);
        }

        Map<String, String> map = new HashMap();
        String tokenName = StpUtil.getTokenName();
        // 获取当前会话的token
        String token = StpUtil.getTokenValue();
        map.put("tokenName", tokenName);
        map.put("token", token);

        return ResponseResult.ok(map);
    }

    /**
     * 注册
     *
     * @param registerDto
     * @return
     */
    @Override
    public ResponseResult<String> register(RegisterDto registerDto) {
        //1.检查参数是否为空
        if (StringUtils.isBlank(registerDto.getUserName()) || StringUtils.isBlank(registerDto.getPassword())) {
            throw new BusinessException(HttpsCode.PARAMS_ERROR, "账号或密码为空");
        }
        //2.判断账户是否唯一
        User user = getOne(Wrappers.<User>lambdaQuery().eq(User::getUserName, registerDto.getUserName()));
        if (user != null) {
            throw new BusinessException(HttpsCode.ACCOUNT_EXIST);
        }
        //3.密码加密
        User newUser = BeanUtil.copyProperties(registerDto, User.class);
        newUser.setPassword(PasswordUtils.encrypt(registerDto.getPassword()));
        //4.保存用户
        save(newUser);
        //5.返回结果
        return ResponseResult.ok("注册成功");
    }

    /**
     * 管理员用户信息查询
     *
     * @param userPageDto
     * @return
     */
    @Override
    public ResponseResult<PageResponse<UserVo>> selectAdminUserList(UserPageDto userPageDto) {
        return getUserVoList(userPageDto, UserEnmu.USER_TYPE_ADMIN);
    }

    @Override
    public ResponseResult<PageResponse<UserVo>> selectUserList(UserPageDto userPageDto) {
        return getUserVoList(userPageDto, UserEnmu.USER_TYPE_USER);
    }

    /**
     * 封禁账户/解封账户
     *
     * @param userId
     * @return
     */
    @Override
    public ResponseResult<String> blockedAndUnsealAccount(Integer userId) {
        //检查用户参数
        if (userId == null) {
            throw new BusinessException(HttpsCode.PARAMS_ERROR);
        }
        //查询用户信息
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException(HttpsCode.PARAMS_ERROR);
        }
        if (UserEnmu.USER_STATUS_BLOCKED.equals(user.getStatus())) {
            //解封
            user.setStatus(UserEnmu.USER_STATUS_NORMAL);
            StpUtil.untieDisable(user.getUserId());
        } else {
            //封禁
            StpUtil.kickout(user.getUserId());
            user.setStatus(UserEnmu.USER_STATUS_BLOCKED);
            StpUtil.disable(user.getUserId(), -1);

        }
        updateById(user);
        return ResponseResult.ok("操作成功");
    }

    /**
     * 用户信息分页查询
     *
     * @param userPageDto
     * @return
     */
    @Override
    public ResponseResult<PageResponse<UserVo>> selectUsers(UserPageDto userPageDto) {
        //1。检查参数
        if (userPageDto.getPageNum() == null || userPageDto.getPageSize() == null) {
            throw new BusinessException(HttpsCode.PARAMS_ERROR, "页码或页容量为空");
        }
        //2.查询
        Page<User> page = page(
                new Page<>(userPageDto.getPageNum(), userPageDto.getPageSize()),
                Wrappers.<User>lambdaQuery()
                        .like(StrUtil.isNotBlank(userPageDto.getUserName()), User::getUserName, userPageDto.getUserName())
                        .like(StrUtil.isNotBlank(userPageDto.getNickName()), User::getNickName, userPageDto.getNickName())
                        .like(StrUtil.isNotBlank(userPageDto.getEmail()), User::getEmail, userPageDto.getEmail())
                        .like(StrUtil.isNotBlank(userPageDto.getPhone()), User::getPhone, userPageDto.getPhone())
                        .eq(StrUtil.isNotBlank(userPageDto.getStatus()), User::getStatus, userPageDto.getStatus())
                        .gt(userPageDto.getStartTime() != null, User::getCreateTime, userPageDto.getStartTime())
                        .lt(userPageDto.getEndTime() != null, User::getCreateTime, userPageDto.getEndTime())
                        .orderBy(true, false, User::getCreateTime)
        );
        //3.脱敏
        List<UserVo> userVos = page.getRecords().stream().map(item -> BeanUtil.copyProperties(item, UserVo.class)).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(userVos)) {
            for (UserVo userVo : userVos) {
                //查询该用户角色
                List<Role> roleByUserId = userMapper.getRoleByUserId(userVo.getUserId());
                userVo.setRoleName(roleByUserId.stream().map(Role::getRoleName).collect(Collectors.toList()));
                userVo.setRoleId(roleByUserId.stream().map(Role::getRoleId).map(String::valueOf).collect(Collectors.toList()));
                //处理创建者
                String createBy = userVo.getCreateBy();
                if (StringUtils.isNotBlank(createBy) && !"注册".equals(createBy)) {
                    User user = getById(createBy);
                    if (user != null) {
                        userVo.setCreateBy(user.getUserName());
                    }
                }
            }
        }
        return ResponseResult.ok(new PageResponse<UserVo>(page, userVos));
    }

    /**
     * 根据id查询用户信息
     *
     * @param userId
     * @return
     */
    @Override
    public ResponseResult<UserVo> getByUserId(Integer userId) {
        //1.检查参数
        if (userId == null) {
            throw new BusinessException(HttpsCode.PARAMS_ERROR, "参数为空");
        }
        User user = getById(userId);
        UserVo userVo = BeanUtil.copyProperties(user, UserVo.class);
        List<Role> roleByUserId = userMapper.getRoleByUserId(Long.valueOf(userId));
        if (CollectionUtil.isNotEmpty(roleByUserId)) {
            userVo.setRoleName(roleByUserId.stream().map(Role::getRoleName).collect(Collectors.toList()));
            userVo.setRoleId(roleByUserId.stream().map(role -> role.getRoleId().toString()).collect(Collectors.toList()));
        }
        return ResponseResult.ok(userVo);
    }

    /**
     * 获取当前登录用户角色列表和权限列表
     *
     * @param userId
     * @return
     */
    @Override
    public ResponseResult<Map<String, Object>> getPermsAndRoles(Integer userId) {
        Map<String, Object> map = new HashMap<>();
        //获取权限列表
        List<String> permissionList = StpUtil.getPermissionList();
        //获取角色列表
        List<String> roleList = StpUtil.getRoleList();
        map.put("roles", roleList);
        map.put("perms", permissionList);
        return ResponseResult.ok(map);
    }

    /**
     * 查询用户信息
     *
     * @param userPageDto
     * @return
     */
    public ResponseResult<PageResponse<UserVo>> getUserVoList(UserPageDto userPageDto, String type) {
        //1。检查参数
        if (userPageDto.getPageNum() == null || userPageDto.getPageSize() == null) {
            throw new BusinessException(HttpsCode.PARAMS_ERROR, "页码或页容量为空");
        }
        //2.查询
        Page<User> page = page(
                new Page<>(userPageDto.getPageNum(), userPageDto.getPageSize()),
                Wrappers.<User>lambdaQuery()
                        .like(StrUtil.isNotBlank(userPageDto.getUserName()), User::getUserName, userPageDto.getUserName())
                        .like(StrUtil.isNotBlank(userPageDto.getNickName()), User::getNickName, userPageDto.getNickName())
                        .like(StrUtil.isNotBlank(userPageDto.getEmail()), User::getEmail, userPageDto.getEmail())
                        .like(StrUtil.isNotBlank(userPageDto.getPhone()), User::getPhone, userPageDto.getPhone())
                        .eq(StrUtil.isNotBlank(type), User::getUserType, type)
                        .eq(StrUtil.isNotBlank(userPageDto.getStatus()), User::getStatus, userPageDto.getStatus())
                        .gt(userPageDto.getStartTime() != null, User::getCreateTime, userPageDto.getStartTime())
                        .lt(userPageDto.getEndTime() != null, User::getCreateTime, userPageDto.getEndTime())
                        .orderBy(true, false, User::getCreateTime)
        );
        //3.脱敏
        List<UserVo> userVos = page.getRecords().stream().map(item -> BeanUtil.copyProperties(item, UserVo.class)).collect(Collectors.toList());

        return ResponseResult.ok(new PageResponse<UserVo>(page, userVos));
    }

    /**
     * 根据id修改用户信息
     *
     * @param userDto
     * @return
     */
    @Override
    public ResponseResult updateUserById(UserDto userDto) {
        //1.检查参数
        if (userDto.getUserId() == null) {
            throw new BusinessException(HttpsCode.PARAMS_ERROR, "用户id为空");
        }
        //2.修改
        User user = BeanUtil.copyProperties(userDto, User.class);
        boolean is = updateById(user);
        if (!is) {
            throw new BusinessException(HttpsCode.MODIFICATION_FAILED);
        }
        if (CollectionUtil.isNotEmpty(userDto.getRoleId())) {
            //删除
            Boolean flag = userMapper.removeRoles(userDto.getUserId());
            //添加
            Boolean b = userMapper.addRoles(userDto.getUserId(), userDto.getRoleId());
        }
        return ResponseResult.ok();
    }

    /**
     * 添加普通用户
     *
     * @param userDto
     * @return
     */
    @Override
    public ResponseResult<String> addUser(UserDto userDto) {
        //1.检查参数是否为空
        if (StringUtils.isBlank(userDto.getUserName()) || StringUtils.isBlank(userDto.getPassword())) {
            throw new BusinessException(HttpsCode.PARAMS_ERROR, "账号或密码为空");
        }
        //2.检查用户是否存在
        long count = count(Wrappers.<User>lambdaQuery().eq(User::getUserName, userDto.getUserName()));
        if (count != 0) {
            throw new BusinessException(HttpsCode.ACCOUNT_EXIST);
        }
        User newUser = BeanUtil.copyProperties(userDto, User.class);
        //密码加密
        newUser.setPassword(PasswordUtils.encrypt(userDto.getPassword()));
        boolean save = save(newUser);
        if (!save) {
            throw new BusinessException(HttpsCode.ADD_FAILED);
        }
        //添加用户角色关系
        if (CollectionUtil.isNotEmpty(userDto.getRoleId())) {
            userMapper.addRoles(newUser.getUserId(), userDto.getRoleId());
        }
        return ResponseResult.ok("添加成功");
    }

    /**
     * 保存用户
     *
     * @param userDto
     * @param userType
     * @return
     */
    private ResponseResult<String> saveUser(UserDto userDto, String userType) {
        //1.检查参数是否为空
        if (StringUtils.isBlank(userDto.getUserName()) || StringUtils.isBlank(userDto.getPassword())) {
            throw new BusinessException(HttpsCode.PARAMS_ERROR, "账号或密码为空");
        }
        //2.检查用户是否存在
        long count = count(Wrappers.<User>lambdaQuery().eq(User::getUserName, userDto.getUserName()));
        if (count != 0) {
            throw new BusinessException(HttpsCode.ACCOUNT_EXIST);
        }
        User newUser = BeanUtil.copyProperties(userDto, User.class);
        //设置为系统用户
        newUser.setUserType(userType);
        //密码加密
        newUser.setPassword(PasswordUtils.encrypt(userDto.getPassword()));
        boolean save = save(newUser);
        if (!save) {
            throw new BusinessException(HttpsCode.ADD_FAILED);
        }
        return ResponseResult.ok("添加成功");
    }

    @Override
    public ResponseResult<String> addAdminUser(UserDto userDto) {
        return saveUser(userDto, "00");
    }
}
